﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Un4seen.Bass;

///< 这两个复制下去
using HCHANNEL = System.Int32;
using HSTREAM = System.Int32;


namespace ZMenFM.BASS
{
    public class Player
    {
        static private List<HCHANNEL> _ChannelList;

        /// <summary>
        /// 初始化BASS库
        /// </summary>
        /// <param name="hWnd">父窗口</param>
        /// <returns>是否初始化成功</returns>
        static public bool InitEnvi(IntPtr hWnd)
        {
            _ChannelList = new List<HCHANNEL>();
            BassNet.Registration("admin@xcoder.in", "2X3914154214");
            bool flag = Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, hWnd);
            if (!flag) return false;

            Bass.BASS_Start();
            return true;
        }

        /// <summary>
        /// 释放Bass库
        /// </summary>
        /// <returns>释放结果</returns>
        static public bool Release()
        {
            while (_ChannelList.Count != 0)
            {
                HCHANNEL Channel = _ChannelList[0];
                Channel_Stop(_ChannelList[0]);

                Stream_Free(Channel);
            }

            return Bass.BASS_Stop();
        }

        static public HSTREAM Stream_Load(String Filename)
        {
            return Bass.BASS_StreamCreateFile(Filename, 0, 0, BASSFlag.BASS_DEFAULT);
        }

        static public HSTREAM Stream_LoadFromUrl(String Url, DOWNLOADPROC dn = null)
        {
            return Bass.BASS_StreamCreateURL(Url, 0, BASSFlag.BASS_DEFAULT, dn, IntPtr.Zero);
        }

        static public void Stream_Free(HSTREAM Stream)
        {
            Bass.BASS_StreamFree(Stream);
        }

        /// <summary>
        /// 播放流
        /// </summary>
        /// <param name="Stream">流句柄</param>
        /// <param name="Loop">是否循环</param>
        /// <param name="Volume">音量 (0 ~ 100)</param>
        /// <returns>频道句柄</returns>
        static public HCHANNEL Stream_Play(HSTREAM Stream, int Volume = 100)
        {
            if (_ChannelList.Contains(Stream)) return 0;

            if (Bass.BASS_ChannelPlay(Stream, true))
            {
                _ChannelList.Add(Stream);
                Channel_SetVolume(Stream, Volume);
                return Stream;
            }
            else return 0;
        }

        /// <summary>
        /// 设置左右声道
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <param name="pan">均衡值 (-100 ~ +100)</param>
        static public void Channel_SetPanning(HCHANNEL Channel, int pan = 0)
        {
            if (pan > 100) return;
            if (pan < -100) return;
            float fPan = (float)pan / 100.0f;

            if (!_ChannelList.Contains(Channel)) return;

            Bass.BASS_ChannelSetAttribute(Channel, BASSAttribute.BASS_ATTRIB_PAN, fPan);
        }

        /// <summary>
        /// 设置音量
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <param name="Volume">音量 (0 ~ 100)</param>
        static public void Channel_SetVolume(HCHANNEL Channel, int Volume)
        {
            if (Volume < 0) Volume = 0;
            if (Volume > 100) Volume = 100;
            float fVolume = (float)Volume / 100.0f;

            if (!_ChannelList.Contains(Channel)) return;

            Bass.BASS_ChannelSetAttribute(Channel, BASSAttribute.BASS_ATTRIB_VOL, fVolume);
        }

        /// <summary>
        /// 暂停
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        static public void Channel_Pause(HCHANNEL Channel)
        {
            if (!_ChannelList.Contains(Channel)) return;
            if (Channel_IsPlaying(Channel)) Bass.BASS_ChannelPause(Channel);
        }

        /// <summary>
        /// 继续播放
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        static public void Channel_Resume(HCHANNEL Channel)
        {
            if (!_ChannelList.Contains(Channel)) return;
            if (Channel_IsPlaying(Channel)) return;

            Bass.BASS_ChannelPlay(Channel, false);
        }

        /// <summary>
        /// 停止
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        static public void Channel_Stop(HCHANNEL Channel)
        {
            Bass.BASS_ChannelStop(Channel);

            /** 从频道列表中移除 */
            for (int i = 0; i < _ChannelList.Count; i++)
            {
                if (_ChannelList[i] == Channel)
                {
                    _ChannelList.RemoveAt(i);
                    break;
                }
            }
        }

        /// <summary>
        /// 暂停所有
        /// </summary>
        static public void Channel_PauseAll()
        {
            for (int i = 0; i < _ChannelList.Count; i++)
            {
                Channel_Pause(_ChannelList[i]);
            }
        }

        /// <summary>
        /// 继续播放所有
        /// </summary>
        static public void Channel_ResumeAll()
        {
            for (int i = 0; i < _ChannelList.Count; i++)
            {
                Channel_Resume(_ChannelList[i]);
            }
        }

        /// <summary>
        /// 停止所有
        /// </summary>
        static public void Channel_StopAll()
        {
            while (_ChannelList.Count != 0)
            {
                Channel_Stop(_ChannelList[0]);
            }
        }

        /// <summary>
        /// 是否播放状态
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <returns></returns>
        static public bool Channel_IsPlaying(HCHANNEL Channel)
        {
            if (!_ChannelList.Contains(Channel)) return false;

            return ((Bass.BASS_ChannelIsActive(Channel)) == BASSActive.BASS_ACTIVE_PLAYING ? true : false);
        }

        /// <summary>
        /// 获取频道长度
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <returns>频道长度秒数</returns>
        static public float Channel_GetLength(HCHANNEL Channel)
        {
            return (float)Bass.BASS_ChannelBytes2Seconds(Channel, Bass.BASS_ChannelGetLength(Channel, BASSMode.BASS_POS_BYTES));
        }

        /// <summary>
        /// 设置播放位置
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <param name="Seconds">秒数</param>
        static public void Channel_SetPos(HCHANNEL Channel, double Seconds)
        {
            if (!_ChannelList.Contains(Channel)) return;

            Bass.BASS_ChannelSetPosition(Channel, (double)Seconds);
        }

        /// <summary>
        /// 获取播放位置
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <returns>秒数</returns>
        static public float Channel_GetPos(HCHANNEL Channel)
        {
            if (!_ChannelList.Contains(Channel)) return -1.0f;
            return (float)Bass.BASS_ChannelBytes2Seconds(Channel, Bass.BASS_ChannelGetPosition(Channel, BASSMode.BASS_POS_BYTES));
        }

        /// <summary>
        /// 滑动 （渐渐）到某个状态
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <param name="Seconds">滑动时间</param>
        /// <param name="Volume">音量</param>
        /// <param name="Pan">平衡值 (-101为不变)</param>
        static public void Channel_SlideTo(HCHANNEL Channel, float Seconds, int Volume, int Pan = -101)
        {
            int Time = (int)(Seconds * 1000);

            if (Volume < 0) Volume = 0;
            if (Volume > 100) Volume = 100;
            float fVolume = (float)Volume / 100.0f;

            Bass.BASS_ChannelSlideAttribute(Channel, BASSAttribute.BASS_ATTRIB_VOL, fVolume, Time);
            if (Pan != -101) Bass.BASS_ChannelSlideAttribute(Channel, BASSAttribute.BASS_ATTRIB_PAN, Pan, Time);
        }

        /// <summary>
        /// 是否在滑动
        /// </summary>
        /// <param name="Channel">频道句柄</param>
        /// <returns>是否在滑动</returns>
        static public bool Channel_IsSliding(HCHANNEL Channel)
        {
            return Bass.BASS_ChannelIsSliding(Channel, BASSAttribute.BASS_ATTRIB_VOL) | Bass.BASS_ChannelIsSliding(Channel, BASSAttribute.BASS_ATTRIB_PAN);
        }
    }
}
